#pragma once
#include<map>
#include<string>
#include "Singleton.h"
#include "ClassField.h"
#include "vector"
using namespace utility;
using namespace std;

namespace reflect {

class object {
public:
	object(){}
	virtual ~object(){}
	virtual void show() = 0;

	void set_className(const string& clssName);
	const string& get_className() const;

	int get_field_count();
	ClassField* get_field(int pos);
	ClassField* get_field(const string& fieldName);
	
	template<typename T>
	void get(const string& fieldName, T& value);

	template<typename T>
	void set(const string& fieldName, const T& value);

private:
	string m_className;
};
typedef object* (*create_object)(void);

class classFactory {
public:
	friend class Singleton<classFactory>;
	void register_class(const string& className, create_object method);
	object* create_class(const string& className);

	void register_class_field(const string& className, const string& fieldName, const string& fieldType, size_t offset);


	int get_field_count(const string& className);
	ClassField* get_field(const string& className, int pos);
	ClassField* get_field(const string& className, const string & fieldname);

private:
	classFactory() {}
	~classFactory() {}


private:
	map<string, create_object> m_classMap;
	map<string, vector<ClassField*>>m_classField;
};


template<typename T>
inline void object::get(const string& fieldName, T& value)
{
	classFactory* factory = Singleton<classFactory>::instance();
	ClassField*field = factory->get_field(m_className, fieldName);
	size_t offset = field->offset();
	value= *(T*)((unsigned char*)this + offset);
}

template<typename T>
inline void object::set(const string& fieldName, const T& value)
{
	classFactory* factory = Singleton<classFactory>::instance();
	ClassField* field = factory->get_field(m_className, fieldName);
	size_t offset = field->offset();
	*(T*)((unsigned char*)this + offset) = value;
}

}